﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace LaTeXGrapher
{
    class FunctionInt : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(- Math.PI / 2, - Math.PI / 2); }
        }

        public Point Max
        {
            get { return new Point(Math.PI, Math.PI); }
        }

        public IEnumerable<double> SpecialPoints 
        { 
            get 
            {
                yield break;  
            } 
        }

        public Vector TickInterval
        {
            get { return new Vector(Math.PI / 2, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return Math.Sin(Math.PI / x);
        }

        #endregion
    }

    class FunctionParab : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-2, -0.5); }
        }

        public Point Max
        {
            get { return new Point(2, 3); }
        }

        public IEnumerable<double> SpecialPoints 
        { 
            get 
            {
                yield return 1;
            }
        }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return x * x;
        }

        #endregion
    }

    class FunctionG : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-10, -10); }
        }

        public Point Max
        {
            get { return new Point(10, 10); }
        }

        public IEnumerable<double> SpecialPoints { get { yield break; } }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            if (Math.Abs(t) == 5)
            {
                if (bX)
                {
                    if (t == 5)
                        return new Vector(-tickWidth, -tickWidth);
                    else
                        return new Vector(-tickWidth, -tickWidth);
                }
                else
                    return new Vector(tickWidth, -3 * tickWidth);
            }
            return null;
        }

        public double Function(double x)
        {
            return (1.0 / 5.0 * Math.Pow(x, 5.0) - 3.0 / 2.0 * Math.Pow(x, 4.0) - 4.0 / 3.0 * x * x * x + 27.0 * x * x - 45.0 * x) / 30;
        }

        #endregion
    }

    class FunctionI : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-2, -2); }
        }

        public Point Max
        {
            get { return new Point(2, 2); }
        }

        public IEnumerable<double> SpecialPoints { get { yield break; } }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            if (Math.Abs(t) == 1)
            {
                if (bX)
                    return new Vector(-t*tickWidth, -0.7*tickWidth);
                else
                    return new Vector(tickWidth, -2.5*tickWidth);
            }
            return null;
        }

        public double Function(double x)
        {
            return (x + 1) * (x - 1) * (x - 1) * x;
            //return ((x - 1) * (x - 1) * x + ((x - 1) * x + ((x - 1) + x) * (x - 1)) * (x + 1));
        }

        #endregion
    }

    class FunctionH : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-10, -10); }
        }

        public Point Max
        {
            get { return new Point(10, 10); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get
            {
                yield return -2;
                yield return -1;
                yield return 0;
                yield return 2;
            }
        }

        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            if (Math.Abs(t) == 5)
            {
                if (bX)
                {
                    if (t == 5)
                        return new Vector(-tickWidth, -tickWidth);
                    else
                        return new Vector(-tickWidth, -tickWidth);
                }
                else
                    return new Vector(tickWidth, -3 * tickWidth);
            }
            return null;
        }

        public double Function(double x)
        {
            if (x == -2)
                return -1;
            if (x < -1)
                return -(x + 3) * (x + 3) + 6;
            if (x >= -1 && x <= 0)
                return x + 3;
            if (x > 0 && x <= 2)
                return -3 * x + 3;
            //if (x > 2)
            return x * x - 4;
        }

        #endregion
    }

    class FunctionAxes : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-10, -10); }
        }

        public Point Max
        {
            get { return new Point(10, 10); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get { yield break; }
        }

        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return 0;
        }

        #endregion
    }

    class FunctionCubic : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-5, -5); }
        }

        public Point Max
        {
            get { return new Point(5, 5); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get
            {
                yield return 0;
                yield return 2;
            }
        }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return 3.0 / 2.0 * (x * x * x / 3.0 - x * x) + 3.0;
        }

        #endregion
    }

    class FunctionHyperbola : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-8, -8); }
        }

        public Point Max
        {
            get { return new Point(8, 8); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get
            {
                yield return 3;
            }
        }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return 4.0 / (x - 1.0) - 2.0;
        }

        #endregion
    }

    class FunctionLnXOverX : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-2, -5); }
        }

        public Point Max
        {
            get { return new Point(8, 5); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get
            {
                yield return 1;
                yield return Math.Exp(1);
            }
        }
        public Vector TickInterval
        {
            get { return new Vector(100, 100); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            if (x < 0.001)
                return -100;
            return Math.Log(x) / (x) * 10;
        }

        #endregion
    }

    class FunctionJ : IFunction2d
    {
        #region IFunction2d Members

        public Point Min
        {
            get { return new Point(-1, -1); }
        }

        public Point Max
        {
            get { return new Point(5,5); }
        }

        public IEnumerable<double> SpecialPoints
        {
            get
            {
                yield break;
            }
        }
        public Vector TickInterval
        {
            get { return new Vector(1, 1); }
        }

        public Vector? MarkTick(bool bX, double t, double tickWidth)
        {
            return null;
        }

        public double Function(double x)
        {
            return x * x * x / 6.0;
        }

        #endregion
    }
}
